#include "EventHandlerObserver.h"

// This demonstrates the observer design pattern
// Here we decouple the code by using seperate event and eventhandler code
// We register one or more observers and they watch a subject for a predefined change
// When a change occures a event function is called and a event is fired
// The event is then handled by one or more objects and this means or more objects call 
// a eventhandler function

// Function to initialize a handler 
int InitEventHandler(EventHandler *Handler, void(*HandlerFunction)(int)){
	Handler->NumberOfObservers = 0;

	Handler->Sensor = false;

	Handler->ghMutex = CreateMutex(
		NULL,              // default security attributes
		FALSE,             // initially not owned
		NULL);             // unnamed mutex

	if (Handler->ghMutex == NULL)
	{
		printf("CreateMutex error: %d\n", GetLastError());
		return 1;
	}


	// Start the worker thread
	// Pass the Handler object as a pointer to the thread
	_beginthreadex(NULL, 0, &WorkerThreadFunction, Handler, 0, NULL);

	return 0;
}

// Function to register a event handler function
void RegisterObserver(EventHandler *Handler, void(*HandlerFunction)(int)){

	// Add the given handler function to the Eventhandeler
	Handler->ListOfObservers[Handler->NumberOfObservers++] = HandlerFunction;
}

// Update function, this function should be called when the observed object (the event handler) 
// changes status. With this function call to fire a event to notify the observer objects that
// handle the actual events
void UpdateHandler(EventHandler *Handler, int Value){

	// The status has changed, so notify all the registred observers
	for (int Index = 0; Index < Handler->NumberOfObservers; Index++){
		Handler->ListOfObservers[Index](Value);
	}

	printf("%s%d\n", "Number of times the events has been handled: ", Value);
}

// This function should be part of a seperate software component
// A example could be a printer component, a function is called 
// for example when there is a paper jam event
void HandlerFunction(int Value){
	printf("%s%d\n", "Handler function called, handeling event number: ", Value);
}

unsigned __stdcall WorkerThreadFunction(void* Data){

	printf("%s\n", "Worker thread started");

	int Counter = 0;
	
	// Cast the void data pointer back to a EventHandler pointer
	EventHandler *Handler = (EventHandler*)Data;

	while (1){

		// Get mutex, for thread saftey, this is needed since the EventHandler object is possible used by the
		// other threads
		WaitForSingleObject(
			Handler->ghMutex,    // handle to mutex
			INFINITE);  // no time-out interval

		if (Handler->Sensor){

			Counter++;

			printf("%s\n", "Starting event sensor");

			// Update handlers, call the registred functions to handle the events
			UpdateHandler(Handler, Counter);

			// Reset the "sensor", normaly the actual sensor will change the sensor status
			// but here we simulate a sensor
			Handler->Sensor = false;
		}

		// Release mutex
		ReleaseMutex(Handler->ghMutex);
	}

	return 0;
}

unsigned __stdcall CommandThreadFunction(void* Data){

	printf("%s\n", "Command thread started");
	EventHandler *Handler = (EventHandler*)Data;

	char Command[100];
	char Value[] = "Event\n";

	while (1){

		fgets(Command, 100, stdin);
		printf("%s\n", Command);

		if (strcmp(Command, Value) == 0){

			printf("%s\n", "Starting event");

			// Wait for EventHandler object to be free
			WaitForSingleObject(
				Handler->ghMutex,    // handle to mutex
				INFINITE);  // no time-out interval

			// Simulate the event, the "sensor" is triggerd
			Handler->Sensor = true;

			// Release mutex, so that other threads can use the shared resource (EvenHandler object)
			ReleaseMutex(Handler->ghMutex);
		}
	}
	return 0;
}
